<?php
/*
# $Id$
#
# Builds a sitemap based on the Sitemap protocol (sitemap.org) and stores it
# in the application's "sitemaps" folder.
*/

use Buan\Config;

// Init
if(!defined('CRON')) {
	die("Cannot execute this script directly.");
}

// Only run every 4 hours
if(time()-$__lastRunTime<(4*60*60)) {
	return 0;
}
set_time_limit(30);

// Prepare some data
$xml  = '<'.'?xml version="1.0" encoding="UTF-8"?'.">\n";
$xml .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';

// Crawl the site
class SitemapBuilder {

	static public $STUBLIST = array();

	private $url;
	private $urlHost;
	private $nodes;

	public function __construct($url) {
		$this->nodes = array();
		$this->url = $url;
		$p = parse_url($url);
		$this->urlHost = $p['host'];
	}

	public function start() {

		// Open page
		$body = file_get_contents($this->url);

		// Extract hyperlinks
		if(preg_match_all("/<a.*?href=\"(.*?)\"/ims", $body, $m)) {
			foreach($m[0] as $k=>$tag) {

				// Vars
				$href = $m[1][$k];
				$url = parse_url($href);

				// Ignore fragment-only links and links that contain fragments
				if(preg_match("/^#/", $href) || isset($url['fragment'])) {
					continue;
				}

				// Ignore mailto:, callto: and ftp: links
				if(isset($url['scheme']) && in_array(strtolower($url['scheme']), array('mailto', 'callto', 'ftp'))) {
					continue;
				}

				// Ignore links that go to external sites
				if(isset($url['scheme']) && $url['host']!=$this->urlHost) {
					continue;
				}

				// For relative URLs, prepend the search URL
				if(!isset($url['scheme'])) {
					$surl = parse_url($this->url);
					$href = preg_replace("/\/+$/", "", $surl['scheme']."://".$surl['host']."/".preg_replace("/^\/+/", "", $href));
				}

				// If the URL is already present in the "ignoreStubs" list then skip
				if(in_array(md5($href), self::$STUBLIST) || $href==$this->url) {
					continue;
				}

				// If the link is a fragment of the current url, just add it to the nodes
				// rather than crawl it
				if(isset($url['fragment']) && preg_replace("/\/+$/", "", str_replace("#{$url['fragment']}", "", $href))==$this->url) {
					$this->addNode($href);
					continue;
				}

				// Add node
				$this->addNode($href);
				self::$STUBLIST[] = md5($href);

				// Crawl the link
				$s = new SitemapBuilder($href);
				$s->start();
				$this->nodes = array_merge($this->nodes, $s->getNodes());
			}
		}
	}

	public function addNode($url) {
		$node = new StdClass();
		$node->loc = $url;
		$node->lastmod = NULL;
		$node->changefreq = NULL;
		$node->priority = NULL;
		$this->nodes[md5($url)] = $node;
	}

	public function getNodes() {
		return $this->nodes;
	}
}
$s = new SitemapBuilder("http://www.scribblecms.co.uk");
$s->start();

// Build the sitemap nodes
$nodes = $s->getNodes();
foreach($nodes as $n) {
	$xml .= "<url>\n";
	$xml .= "<loc>".htmlentities($n->loc, ENT_COMPAT, 'UTF-8')."</loc>\n";
	$xml .= isset($n->lastmod) && $n->lastmode!==NULL ? "<lastmod>{$n->lastmod}</lastmod>\n" : '';
	$xml .= isset($n->changefreq) && $n->changefreq!==NULL ? "<changefreq>{$n->changefreq}</changefreq>\n" : '';
	$xml .= isset($n->priority) && $n->priority!==NULL ? "<priority>{$n->priority}</priority>\n" : '';
	$xml .= "</url>\n";
}

// Write the sitemap file
$xml .= '</urlset>';
file_put_contents(Config::get('app.dir.sitemaps').'/sitemap.xml', $xml);
?>